else
tsc_stamp = t->local_tsc_stamp;
- if ( d->arch.tsc_mode == TSC_MODE_PVRDTSCP &&
- boot_cpu_has(X86_FEATURE_RDTSCP) )
- write_rdtscp_aux(d->arch.incarnation);
+ if ( boot_cpu_has(X86_FEATURE_RDTSCP) )
+ {
+ if ( d->arch.tsc_mode == TSC_MODE_PVRDTSCP )
+ write_rdtscp_aux(d->arch.incarnation);
+ else
+ write_rdtscp_aux(0);
+ }
/* Don't bother unless timestamps have changed or we are forced. */
if ( !force && (u->tsc_timestamp == tsc_stamp) )
* PV SoftTSC Emulation.
*/
-void pv_soft_rdtsc(struct vcpu *v, struct cpu_user_regs *regs)
+void pv_soft_rdtsc(struct vcpu *v, struct cpu_user_regs *regs, int rdtscp)
{
s_time_t now = get_s_time();
struct domain *d = v->domain;
regs->eax = (uint32_t)now;
regs->edx = (uint32_t)(now >> 32);
+
+ if ( rdtscp )
+ regs->ecx =
+ (d->arch.tsc_mode == TSC_MODE_PVRDTSCP) ? d->arch.incarnation : 0;
}
static int host_tsc_is_safe(void)
printk(",khz=%"PRIu32"",d->arch.tsc_khz);
if ( d->arch.incarnation )
printk(",inc=%"PRIu32"",d->arch.incarnation);
- if ( !d->arch.vtsc )
+ if ( !(d->arch.vtsc_kerncount | d->arch.vtsc_usercount) )
{
printk("\n");
continue;
regs->edx = d;
}
+static int emulate_invalid_rdtscp(struct cpu_user_regs *regs)
+{
+ char opcode[3];
+ unsigned long eip, rc;
+ struct vcpu *v = current;
+
+ eip = regs->eip;
+ if ( (rc = copy_from_user(opcode, (char *)eip, sizeof(opcode))) != 0 )
+ {
+ propagate_page_fault(eip + sizeof(opcode) - rc, 0);
+ return EXCRET_fault_fixed;
+ }
+ if ( memcmp(opcode, "\xf\x1\xf9", sizeof(opcode)) )
+ return 0;
+ eip += sizeof(opcode);
+ pv_soft_rdtsc(v, regs, 1);
+ instruction_done(regs, eip, 0);
+ return EXCRET_fault_fixed;
+}
+
static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
{
char sig[5], instr[2];
if ( likely(guest_mode(regs)) )
{
- if ( !emulate_forced_invalid_op(regs) )
+ if ( !emulate_invalid_rdtscp(regs) &&
+ !emulate_forced_invalid_op(regs) )
do_guest_trap(TRAP_invalid_op, regs, 0);
return;
}
twobyte_opcode:
/*
- * All two-byte opcodes, except RDTSC (0x31) are executable only from
- * guest kernel mode (virtual ring 0).
+ * All 2 and 3 byte opcodes, except RDTSC (0x31) and RDTSCP (0x1,0xF9)
+ * are executable only from guest kernel mode (virtual ring 0).
*/
opcode = insn_fetch(u8, code_base, eip, code_limit);
if ( !guest_kernel_mode(v, regs) &&
+ (opcode != 0x1) && /* always emulate rdtscp */
!((opcode == 0x31) && v->domain->arch.vtsc) )
goto fail;
goto fail;
switch ( opcode )
{
+ case 0x1: /* RDTSCP */
+ if ( insn_fetch(u8, code_base, eip, code_limit) != 0xf9 )
+ goto fail;
+ pv_soft_rdtsc(v, regs, 1);
+ break;
+
case 0x06: /* CLTS */
(void)do_fpu_taskswitch(0);
break;
}
case 0x31: /* RDTSC */
- pv_soft_rdtsc(v, regs);
+ pv_soft_rdtsc(v, regs, 0);
break;
case 0x32: /* RDMSR */
uint64_t acpi_pm_tick_to_ns(uint64_t ticks);
uint64_t ns_to_acpi_pm_tick(uint64_t ns);
-void pv_soft_rdtsc(struct vcpu *v, struct cpu_user_regs *regs);
+void pv_soft_rdtsc(struct vcpu *v, struct cpu_user_regs *regs, int rdtscp);
void tsc_set_info(struct domain *d, uint32_t tsc_mode, uint64_t elapsed_nsec,
uint32_t gtsc_khz, uint32_t incarnation);